home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / language / iconv8_s.arc / ICONT.ARC / LINK.C < prev    next >
C/C++ Source or Header  |  1990-03-28  |  10KB  |  382 lines

  1. /*
  2.  * link.c -- linker main program that controls the linking process.
  3.  */
  4.  
  5. #include "..\h\config.h"
  6. #include "general.h"
  7. #include "tproto.h"
  8. #include "globals.h"
  9. #include "link.h"
  10. #include "..\h\paths.h"
  11. #include "..\h\header.h"
  12.  
  13. #ifdef Header
  14. #include "hdr.h"
  15.  
  16. #ifndef MaxHeader
  17. #define MaxHeader MaxHdr
  18. #endif                    /* MaxHeader */
  19.  
  20. #endif                    /* Header */
  21.  
  22. /*
  23.  * Prototype.
  24.  */
  25.  
  26. hidden    novalue    setexe    Params((char *fname));
  27.  
  28.  
  29. /*
  30.  * The following code is operating-system dependent [@link.01].  Include
  31.  *  system-dependent files and declarations.
  32.  */
  33.  
  34. #if PORT
  35.    /* nothing to do */
  36. Deliberate Syntax Error
  37. #endif                    /* PORT */
  38.  
  39. #if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || VM || VMS
  40.    /* nothing to do */
  41. #endif                    /* AMIGA || ATARI_ST || HIGHC_386 ... */
  42.  
  43. #if MSDOS
  44. #if MICROSOFT || TURBO
  45. #include <fcntl.h>
  46. #endif                    /* MICROSOFT || TURBO */
  47. #endif                    /* MSDOS */
  48.  
  49. #if MVS
  50. char *routname;                /* real output file name */
  51. #endif                    /* MVS */
  52.  
  53. #if OS2
  54. #if MICROSOFT
  55. #include <fcntl.h>
  56. #endif                    /* MICROSOFT */
  57. #endif                    /* OS2 */
  58.  
  59. #if UNIX
  60. #ifdef CRAY
  61. #define word word_fubar
  62. #include <sys\types.h>
  63. #include <sys\stat.h>
  64. #undef word
  65. #else                    /* CRAY */
  66. #include <sys\types.h>
  67. #include <sys\stat.h>
  68. #endif                    /* CRAY */
  69. #endif                    /* UNIX */
  70.  
  71. /*
  72.  * End of operating-system specific code.
  73.  */
  74.  
  75. FILE *infile;                /* input file (.u1 or .u2) */
  76. FILE *outfile;                /* interpreter code output file */
  77.  
  78. #ifdef DeBugLinker
  79. FILE *dbgfile;                /* debug file */
  80. static char dbgname[MaxFileName];    /* debug file name */
  81. #endif                    /* DeBugLinker */
  82.  
  83. char inname[MaxFileName];        /* input file name */
  84. static char icnname[MaxFileName];    /* icon source file name */
  85.  
  86. struct lfile *llfiles = NULL;        /* List of files to link */
  87.  
  88. #ifdef EvalTrace
  89. int colmno = 0;                /* current source program colm number */
  90. #endif                    /* EvalTrace */
  91.  
  92. int lineno = 0;                /* current source program line number */
  93. int fatals = 0;                /* number of errors encountered */
  94.  
  95. /*
  96.  *  ilink - link a number of files, returning error count
  97.  */
  98. int ilink(ifiles,outname)
  99. char **ifiles;
  100. char *outname;
  101.    {
  102.  
  103.    int i;
  104.    struct lfile *lf,*lfls;
  105.    char *filename;            /* name of current input file */
  106.  
  107.    linit();                /* initialize memory structures */
  108.    while (*ifiles)
  109.       alsolink(*ifiles++);        /* make initial list of files */
  110.  
  111.    /*
  112.     * Phase I: load global information contained in .u2 files into
  113.     *  data structures.
  114.     *
  115.     * The list of files to link is maintained as a queue with llfiles
  116.     *  as the base.  lf moves along the list.  Each file is processed
  117.     *  in turn by forming .u2 and .icn names from each file name, each
  118.     *  of which ends in .u1.  The .u2 file is opened and globals is called
  119.     *  to process it.  When the end of the list is reached, lf becomes
  120.     *  NULL and the loop is terminated, completing phase I.  Note that
  121.     *  link instructions in the .u2 file cause files to be added to list
  122.     *  of files to link.
  123.     */
  124.    for (lf = llfiles; lf != NULL; lf = lf->lf_link) {
  125.       filename = lf->lf_name;
  126.       makename(inname, SourceDir, filename, U2Suffix);
  127.       makename(icnname, TargetDir, filename, SourceSuffix);
  128.  
  129. #if MVS || VM
  130. /*
  131.  * Even though the ucode data is all reasonable text characters, use
  132.  *  of text I/O may cause problems if a line is larger than LRECL.
  133.  *  This is likely to be true with any compiler, though the precise
  134.  *  disaster which results may vary.
  135.  */
  136.       infile = fopen(inname, ReadBinary);
  137. #else
  138.       infile = fopen(inname, ReadText);
  139. #endif                    /* MVS || VM */
  140.  
  141.       if (infile == NULL)
  142.          quitf("cannot open %s",inname);
  143.       readglob();
  144.       fclose(infile);
  145.       }
  146.  
  147.    /* Phase II: resolve undeclared variables and generate code. */
  148.  
  149.    /*
  150.     * Open the output file.
  151.     */
  152.  
  153. #ifdef WATERLOO_C_V3_0
  154.    strcat(outname," (BIN");
  155. #endif                    /* WATERLOO_C_V3_0 */
  156.  
  157. #if MVS
  158.    routname = outname;
  159.    outfile = tmpfile();         /* write icode to temporary file to
  160.                                    avoid fseek-PDS limitations */
  161. #else                    /* MVS */
  162.    outfile = fopen(outname, WriteBinary);
  163. #endif                    /* MVS */
  164.  
  165. /*
  166.  * The following code is operating-system dependent [@link.02].  Set
  167.  *  untranslated mode if necessary.
  168.  */
  169.  
  170. #if PORT
  171.    /* probably nothing */
  172. Deliberate Syntax Error
  173. #endif                    /* PORT */
  174.  
  175. #if AMIGA || ATARI_ST || HIGHC_386 || MACINTOSH || MVS || UNIX || VM || VMS
  176.    /* nothing to do */
  177. #endif                    /* AMIGA || ATARI_ST || ... */
  178.  
  179. #if MSDOS
  180. #if LATTICE
  181.    fmode(outfile,1);            /* set for untranslated mode */
  182. #endif                    /* LATTICE */
  183. #if MICROSOFT || TURBO
  184.    setmode(fileno(outfile),O_BINARY);    /* set for untranslated mode */
  185. #endif                    /* MICROSOFT || TURBO */
  186. #endif                    /* MSDOS */
  187.  
  188. #if OS2
  189. #if MICROSOFT
  190.    setmode(fileno(outfile),O_BINARY);
  191. #endif                    /* MICROSOFT */
  192. #endif                    /* OS2 */
  193.  
  194. /*
  195.  * End of operating-system specific code.
  196.  */
  197.  
  198.    if (outfile == NULL) 
  199.       quitf("cannot create %s",outname);
  200.  
  201. #ifdef Header
  202.    /*
  203.     * Open Header, which contains the start-up program and copy it to the
  204.     *  output file.  Then, write out null bytes to past the end of the
  205.     *  start-up program.
  206.     */
  207.    {
  208.    int hsize;
  209.    char hname[MaxFileName];
  210.    char hdrdat[MaxHeader+1];
  211.  
  212. #if MACINTOSH
  213. #if MPW
  214.       {  /* Look for header in same directory as the linker */
  215.       char *p, *rindex();
  216.  
  217.       p = (char *)getenv("Command");
  218.       if (p) {
  219.          strcpy(hname,p);
  220.          p = rindex(hname,':') + 1;
  221.          }
  222.       else
  223.          p = hname;
  224.       strcpy(p,HeaderPath);
  225.       fprintf(stderr,HeaderPath);
  226.       fflush(stderr);
  227.       }
  228. #endif                    /* MPW */
  229. #endif                    /* MACINTOSH */
  230.  
  231.    fwrite(iconxhdr, sizeof(char), MaxHeader, outfile);
  232.    }
  233. #endif                    /* Header */
  234.  
  235.    for (i = sizeof(struct header); i--;)
  236.       putc(0, outfile);
  237.    fflush(outfile);
  238.    if (ferror(outfile) != 0)
  239.       quit("unable to write to icode file");
  240.  
  241. #ifdef DeBugLinker
  242.    /*
  243.     * Open the .ux file if debugging is on.
  244.     */
  245.    if (Dflag) {
  246.       makename(dbgname, TargetDir, llfiles->lf_name, ".ux");
  247.       dbgfile = fopen(dbgname, WriteText);
  248.       if (dbgfile == NULL)
  249.          quitf("cannot create %s", dbgname);
  250.       }
  251. #endif                    /* DeBugLinker */
  252.  
  253.    /*
  254.     * Loop through input files and generate code for each.
  255.     */
  256.    lfls = llfiles;
  257.    while (lf = getlfile(&lfls)) {
  258.       filename = lf->lf_name;
  259.       makename(inname, SourceDir, filename, U1Suffix);
  260.       makename(icnname, TargetDir, filename, SourceSuffix);
  261.  
  262. #if MVS || VM
  263.       infile = fopen(inname, ReadBinary);
  264. #else                    /* MVS || VM */
  265.       infile = fopen(inname, ReadText);
  266. #endif                    /* MVS || VM */
  267.  
  268.       if (infile == NULL)
  269.          quitf("cannot open %s", inname);
  270.       gencode();
  271.       fclose(infile);
  272.       }
  273.    gentables();        /* Generate record, field, global, global names,
  274.                static, and identifier tables. */
  275.    fclose(outfile);
  276.    lmfree();
  277.    if (fatals > 0)
  278.       return fatals;
  279.    setexe(outname);
  280.    return 0;
  281.    }
  282.  
  283. /*
  284.  * lwarn - issue a linker warning message.
  285.  */
  286. novalue lwarn(s1, s2, s3)
  287. char *s1, *s2, *s3;
  288.    {
  289.    fprintf(stderr, "%s: ", icnname);
  290.    if (lineno)
  291.       fprintf(stderr, "Line %d # :", lineno);
  292.    fprintf(stderr, "\"%s\": %s%s\n", s1, s2, s3);
  293.    fflush(stderr);
  294.    }
  295.  
  296. /*
  297.  * lfatal - issue a fatal linker error message.
  298.  */
  299.  
  300. novalue lfatal(s1, s2)
  301. char *s1, *s2;
  302.    {
  303.  
  304.    fprintf(stderr, "%s: ", icnname);
  305.    if (lineno)
  306.       fprintf(stderr, "Line %d # : ", lineno);
  307.    fprintf(stderr, "\"%s\": %s\n", s1, s2);
  308.    fatals++;
  309.    }
  310.  
  311. /*
  312.  * setexe - mark the output file as executable
  313.  */
  314.  
  315. static novalue setexe(fname)
  316. char *fname;
  317.    {
  318.  
  319. /*
  320.  * The following code is operating-system dependent [@link.03].  It changes the
  321.  *  mode of executable file so that it can be executed directly.
  322.  */
  323.  
  324. #if PORT
  325.    /* something is needed */
  326. Deliberate Syntax Error
  327. #endif                    /* PORT */
  328.  
  329. #if AMIGA
  330.    /* not necessary */
  331. #endif                    /* AMIGA */
  332.  
  333. #if ATARI_ST || MSDOS || MVS || OS2 || VM || V